/*************************************************************************
*** Copyright (c) 2012, agiant,Inc.
***
*** File name  : errorcode.h
***
*** Module     : ErrorCode define for all module
***
*** Author     : Jelin sui
***
*** Version    : 1.0
***
*** Created On : 05/31/2012
***
*** Description:
***            This APIs for Error Code Define
***
*** Modification histroy:
***
**************************************************************************/

/*
ERRORCODE   MODULE  SUBMODULE   DESCRIPTION		DETAIL
1000000      coca     SDK 	"InitSDK Error"		""

the format of print in log 
[Level: 1] [ERRORCODE=code][mod.submod][desc][detail]
*/

#ifndef _ERRORCODE_H
#define _ERRORCODE_H

#include <map>
#include <string>
#include <stdarg.h>
#include <stdio.h>

using namespace std;

class CdmErrorCode
{
public:
	string ErrMsg(int code,const char* fmt,...)
	{
            char szDetail[1024] = {0};
	    va_list vl;
            string strMsg;
            string strMod;
            string strSub;
            string strDes;
            string strDetail;

            char szcode[50];
            _snprintf(szcode,sizeof(szcode)-1,"[ERRCODE=%d]",code);
            strMsg = szcode;
            ErrorMsgMap::iterator it = m_MsgMap.find(code); 
            if (it==m_MsgMap.end())
            {
                strMsg += " NotFound!";
                return strMsg;
            }

            va_start(vl, fmt);
            int n = vsnprintf(szDetail,sizeof(szDetail)-1, fmt, vl);
            va_end(vl);

            if (!it->second.module.empty())
                strMod = "["+it->second.module;
            if (!it->second.submod.empty())
                strSub = "."+it->second.submod+"]";
            if (!it->second.desc.empty())
                strDes = "["+it->second.desc+"]";
            if (n>0)
            {
                strDetail = "[";
                strDetail = strDetail+szDetail+"]";               
            }
           
            strMsg += strMod+strSub+strDes+strDetail;
            
            return strMsg;
	}

	string ErrMsg(int code)
        {
            return ErrMsg(code,"");
        }
	
	static CdmErrorCode& Instance()
        {
            static CdmErrorCode m_sCdmErrCodeObj;
            return m_sCdmErrCodeObj;
        }
private:	
	CdmErrorCode(){};
	CdmErrorCode(const CdmErrorCode&);
	CdmErrorCode& operator = (const CdmErrorCode&);
public:
	void DefineErrMsg(int code,string module,string submod,string desc)
        {
            ErrorMsg msg;
            msg.module = module;
            msg.submod = submod;
            msg.desc   = desc;

            m_MsgMap.insert(make_pair(code,msg));
        }

private:
	int m_nErrorCode;
	typedef struct _ErrorMsg
	{
		string module;
		string submod;
		string desc;
		string detail;
	}ErrorMsg;

typedef map<int,ErrorMsg> ErrorMsgMap;	

	 ErrorMsgMap m_MsgMap;
	
};

/******************************************************************************
		how to use the api
1. in your app code ,call <InitErrorCode()> at <main> eg,InitErrorCode()
2. in your .h file,define ErrorCode as follow
   a. CDM_DECLARE_ERROR_BEGIN(##MOD),eg. CDM_DECLARE_ERROR_BEGIN(COCA)
   b.define macro for ERRORCODE. eg: <#define COCA_SDK_INIT_ERR 1000000>
   c.define a meaning of ERRORCODE by [CDM_DECLARE_ERROR] macro in your code
     eg: CDM_DECLARE_ERROR(COCA_SDK_INIT_ERR,"coca","sdk","initsdk error")
   d. CDM_DECLARE_ERROR_END()  end for define error code

3. in your code,call [CDM_ERR_MSG] by 'code' and 'fmt' argument.
   eg:string strError = CDM_ERR_MSG(COCA_SDK_INIT_ERR,"NetSDKInit=%d!",ret);
   or call [CDM_ERR_MSG2] by 'code' argument. 
   eg:string strError = CDM_ERR_MSG(COCA_SDK_INIT_ERR);

4. that's all ,enjoy it.
******************************************************************************/
#define CDM_DECLARE_ERROR(CODE,MOD,SUBMOD,DES)	\
	CdmErrorCode::Instance().DefineErrMsg(CODE,MOD,SUBMOD,DES);

#define CDM_ERR_MSG(code,fmt,arg...)	\
        CdmErrorCode::Instance().ErrMsg(code,fmt,##arg);

#define CDM_ERR_MSG2(code)	\
        CdmErrorCode::Instance().ErrMsg(code);

/*****************************************************************************/
/********************Define ErrorCode for All Module**************************/
/*****************************************************************************/


#define CDM_DECLARE_ERROR_BEGIN(MOD)	\
	static void InitErrorCode()		\
	{				\
	    static int i=0;		\
	    if (i++ != 0)		\
            {   			\
		return ;		\
	    }	

#define CDM_DECLARE_ERROR_END()		\
	}

/**********************************test for use this api *****************

CDM_DECLARE_ERROR_BEGIN(COCA)

#define COCA_SDK_INI_ERR 		1000000
#define COCA_AAS_REG_ERR      		1000001
#define COCA_SIP_REG_ERR      		1000002

//CDM_DECLARE_ERROR(COCA_SDK_INIT_ERR,"coca","sdk","initsdk error","NETSDK_Init ret=-1!")

CDM_DECLARE_ERROR(COCA_SDK_INI_ERR,"coca","sdk","initsdk error")
//CDM_DECLARE_ERROR(COCA_AAS_REG_ERR,"coca","aas","connect aas failure","ret=-5!")
CDM_DECLARE_ERROR(100,"coca","aas","connect aas failure")
//CDM_DECLARE_ERROR(COCA_AAS_REG_ERR,"coca","sip","register","401")
CDM_DECLARE_ERROR(COCA_AAS_REG_ERR,"coca","sip","registor")


#define MT_SIP_LIVE_ERR			1100000
//CDM_DECLARE_ERROR(MT_SIP_LIVE_ERR,"mt","sip","invite livevideo","503")
CDM_DECLARE_ERROR(MT_SIP_LIVE_ERR,"mt","sip","invite livevideo")

CDM_DECLARE_ERROR_END()

***************************************************************************/

#endif 
